﻿using Microsoft.AspNetCore.Http;
using System.Net;
using System.Net.Sockets;
using System.Web;
using UAParser;

namespace RuoVea.ExFilter;

/// <summary>
/// Http 拓展类
/// </summary>
public static class HttpContextExtensions
{
    #region 设置规范化文档
    /// <summary>
    /// 设置规范化文档自动登录
    /// </summary>
    /// <param name="httpContext">HttpContext</param>
    /// <param name="accessToken">accessToken</param>
    public static void SigninToSwagger(this HttpContext httpContext, string accessToken)
    {
        if (httpContext == null) return;
        if (httpContext.Response == null) return;
        // 设置 Swagger 刷新自动授权
        httpContext.Response.Headers["access-token"] = accessToken;
    }

    /// <summary>
    /// 设置规范化文档退出登录
    /// </summary>
    /// <param name="httpContext">HttpContext</param>
    public static void SignoutToSwagger(this HttpContext httpContext)
    {
        if (httpContext == null) return;
        if (httpContext.Response == null) return;
        httpContext.Response.Headers["access-token"] = "invalid_token";
    }

    #endregion

    #region 获取完整请求地址
    /// <summary>
    /// 获取完整请求地址
    /// </summary>
    /// <param name="request">HttpRequest</param>
    /// <returns>完整请求地址</returns>
    public static string GetRequestUrlAddress(this HttpRequest request)
    {
        return new StringBuilder()
                .Append(request.Scheme)
                .Append("://")
                .Append(request.Host)
                .Append(request.PathBase)
                .Append(request.Path)
                .Append(request.QueryString)
                .ToString();
    }
    #endregion

    #region 获取站点 协议://Host GetRequestHost
    /// <summary>
    /// 获取站点 (http|s)://Host
    /// </summary>
    /// <param name="request">HttpRequest</param>
    /// <returns>完整请求地址</returns>
    public static string GetRequestHost(this HttpRequest request)
    {
        if (request==null) return null;
        return new StringBuilder()
                .Append(request.Scheme)
                .Append("://")
                .Append(request.Host.Host)
                .ToString();
    }
    #endregion

    #region 获取站点 协议://Host:端口 GetRequestHostPort
    /// <summary>
    /// 获取站点 (http|s)://Host:端口
    /// </summary>
    /// <param name="request">HttpRequest</param>
    /// <returns>完整请求地址</returns>
    public static string GetRequestHostPort(this HttpRequest request)
    {
        return new StringBuilder()
                .Append(request.Scheme)
                .Append("://")
                .Append(request.Host.Host)
                .Append(":")
                .Append(request.Host.Port)
                .ToString();
    }
    #endregion

    #region 获取来源地址 GetRefererUrl
    /// <summary>
    /// 获取来源地址
    /// </summary>
    /// <param name="request">HttpRequest</param>
    /// <param name="refererHeaderKey">刷新的key值</param>
    /// <returns>来源地址</returns>
    public static string GetRefererUrl(this HttpRequest request, string refererHeaderKey = "Referer")
    {
        return request.Headers[refererHeaderKey].ToString();
    }
    #endregion

    #region 获得浏览器信息 GetBrowser
    /// <summary>
    /// 获得浏览器 Chrome、Safari、Firefox、Edg、Opera、IE
    /// </summary>
    /// <returns>字符串数组</returns>
    public static string GetBrowser(this HttpContext httpContext)
    {
        var browserAgent = httpContext?.Request?.Headers["User-Agent"].ToString();
        if (string.IsNullOrWhiteSpace(browserAgent))
            return null;
        string res;
        if (browserAgent.Contains("Chrome"))
            res = "Chrome";
        else if (browserAgent.Contains("Safari"))
            res = "Safari";
        else if (browserAgent.Contains("Firefox"))
            res = "Firefox";
        else if (browserAgent.Contains("Edg"))
            res = "Microsoft Edge";
        else if (browserAgent.Contains("Opera"))
            res = "Opera";
        else if (browserAgent.Contains("MSIE"))
            res = "IE";
        else
            res = browserAgent;
        return res;
    }

    /// <summary>
    /// 请求UserAgent信息
    /// </summary>
    public static string UserAgent(this HttpContext httpContext)
    {
        if (httpContext == null) return null;
        if (httpContext.Request == null) return null;
        return httpContext.Request.Headers["User-Agent"];
    }
    /// <summary>
    /// 获取 User-Agent 所有信息
    /// </summary>
    public static ClientInfo GetDefault(this HttpContext httpContext)
    {
        if (httpContext == null) return null;
        var uaString = httpContext.UserAgent();
        if (string.IsNullOrWhiteSpace(uaString)) return null;
        return Parser.GetDefault().Parse(uaString);
    }
    #endregion

    #region 得到操作系统版本 GetOSVersion
    /// <summary>
    /// 得到操作系统版本
    /// </summary>
    /// <returns></returns>
    public static string GetOSVersion(this HttpContext httpContext)
    {
        if (httpContext == null) return null;
        var osVersion = string.Empty;
        var userAgent = httpContext.UserAgent();
        if (string.IsNullOrWhiteSpace(userAgent)) return null;
        if (userAgent.Contains("NT 10"))
            osVersion = "Windows 10";
        else if (userAgent.Contains("NT 6.3"))
            osVersion = "Windows 8";
        else if (userAgent.Contains("NT 6.1"))
            osVersion = "Windows 7";
        else if (userAgent.Contains("NT 6.0"))
            osVersion = "Windows Vista/Server 2008";
        else if (userAgent.Contains("NT 5.2"))
            osVersion = "Windows Server 2003";
        else if (userAgent.Contains("NT 5.1"))
            osVersion = "Windows XP";
        else if (userAgent.Contains("NT 5"))
            osVersion = "Windows 2000";
        else if (userAgent.Contains("NT 4"))
            osVersion = "Windows NT4";
        else if (userAgent.Contains("Android"))
            osVersion = "Android";
        else if (userAgent.Contains("Me"))
            osVersion = "Windows Me";
        else if (userAgent.Contains("98"))
            osVersion = "Windows 98";
        else if (userAgent.Contains("95"))
            osVersion = "Windows 95";
        else if (userAgent.Contains("Mac"))
            osVersion = "Mac";
        else if (userAgent.Contains("Unix"))
            osVersion = "UNIX";
        else if (userAgent.Contains("Linux"))
            osVersion = "Linux";
        else if (userAgent.Contains("SunOS"))
            osVersion = "SunOS";
        return osVersion;
    }
    #endregion

    #region UserAgent信息 UserAgentInfo
    /// <summary>
    /// UserAgent信息
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns>手机型号,操作系统(版本),浏览器(版本)</returns>
    public static (string PhoneModel, string OS,string Browser) UserAgentInfo(this HttpContext httpContext)
    {
        if (httpContext == null) return (null, null, null);
        if (string.IsNullOrWhiteSpace(httpContext.UserAgent())) return (null, null, null);
        var parser = Parser.GetDefault();
        var clientInfo = parser.Parse(httpContext.UserAgent());
        if (clientInfo == null)   return (null, null, null);
        return (clientInfo.Device?.ToString(),clientInfo.OS?.ToString(), clientInfo.UA?.ToString());
    } 
    #endregion

    #region 远程路径Encode处理,会保证开头是/，结尾也是/
    /// <summary>
    /// 远程路径Encode处理,会保证开头是/，结尾也是/
    /// </summary>
    /// <param name="remotePath"></param>
    /// <returns></returns>
    public static string EncodeRemotePath(this string remotePath)
    {
        if (remotePath == "/")
            return remotePath;

        var endWith = remotePath.EndsWith("/");
        var part = remotePath.Split('/');
        remotePath = "";
        foreach (var s in part)
        {
            if (s == "")
                continue;
            if (remotePath != "")
                remotePath += "/";
            remotePath += HttpUtility.UrlEncode(s).Replace("+", "%20");
        }
        remotePath = (remotePath.StartsWith("/") ? "" : "/") + remotePath + (endWith ? "/" : "");
        return remotePath;
    } 
    #endregion

    #region IP 地址相关
    /// <summary>
    /// 获取本机 IPv4地址
    /// </summary>
    /// <param name="context">HttpContext</param>
    /// <returns>IPv4地址</returns>
    public static string GetLocalIpAddressToIPv4(this HttpContext context) => context?.Connection?.LocalIpAddress?.MapToIPv4()?.ToString();

    /// <summary>
    /// 获取本机 IPv6地址
    /// </summary>
    /// <param name="context">HttpContext</param>
    /// <returns>IPv6地址</returns>
    public static string GetLocalIpAddressToIPv6(this HttpContext context) => context?.Connection?.LocalIpAddress?.MapToIPv6()?.ToString();

 
    /// <summary>
    /// 获取远程 IPv6地址
    /// </summary>
    /// <param name="context">HttpContext</param>
    /// <returns>远程 IPv6地址</returns>
    public static string GetRemoteIpAddressToIPv6(this HttpContext context) => context?.Connection?.RemoteIpAddress?.MapToIPv6()?.ToString();

    #region 获得IP地址
    /// <summary>
    /// 获得IP地址 业务使用
    /// </summary>
    /// <returns>字符串数组</returns>
    public static string GetIp(this HttpContext context)
    {
        if (context == null) return null;
        if (context.Request == null) return null;
        HttpRequest request = context.Request;
        string ip = string.Empty;
        if (context.Connection.RemoteIpAddress != null)
        {
            if (request.Headers.ContainsKey("X-Real-IP"))
                ip = request.Headers["X-Real-IP"].FirstOrDefault();
            if (request.Headers.ContainsKey("X-Forwarded-For"))
                ip = request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
                ip = context.Connection.RemoteIpAddress?.MapToIPv4()?.ToString();
        }
        return ip;
    }
    #endregion

    /// <summary>
    /// 得到局域网IP地址
    /// </summary>
    /// <returns></returns>
    public static string GetLanIp(this HttpContext context)
    {
        foreach (var hostAddress in Dns.GetHostAddresses(Dns.GetHostName()))
            if (hostAddress.AddressFamily == AddressFamily.InterNetwork)
                return hostAddress.ToString();
        return string.Empty;
    }
    #endregion
}
